import { actionBuilder, useApp } from '../utils';

export const Namespace = 'app';

type State = {
    loading: false;
};
type Action = {
    type: string;
    payload: any;
};

const model = {
    namespace: Namespace,
    state: {
        loading: false,
    },
    reducers: {
        REDUCE(state: State, { payload }: Action) {
            if (!payload) return state;

            return {
                ...state,
                ...payload,
            };
        },
        SET_LOADING(state: State, { payload }: Action) {
            return {
                ...state,
                loading: payload,
            };
        },
    },
    effects: {
        *ADD_MODEL({ payload: model }: Action, { put, call }: any) {
            const app = yield call(useApp);

            const { namespace, subscriptions, ...modelProps } = model;

            const promiseRef: { resolve(...args: any[]): void } = {} as any;
            const promise = new Promise<void>((resolve) => {
                promiseRef.resolve = resolve;
            });

            const mountEmitter = function (...args) {
                promiseRef.resolve(...args);

                return () => {};
            };

            const _origin_modelDidMount = subscriptions?.modelDidMount;

            const modelDidMount = _origin_modelDidMount
                ? function (...args: any[]) {
                      // @ts-ignore
                      const result: any = _origin_modelDidMount(...args);

                      if (result instanceof Promise) {
                          return result.then(mountEmitter);
                      } else {
                          return mountEmitter();
                      }
                  }
                : mountEmitter;

            const dealedModel = {
                namespace,
                ...modelProps,
                subscriptions: {
                    ...(subscriptions || {}),
                    modelDidMount,
                },
            };
            yield call(app.model, dealedModel);

            yield promise;
        },
        *REMOVE_MODEL({ payload: modelNamespace }: Action, { put, call }) {
            const app = yield call(useApp);

            yield call(app.unmodel, modelNamespace);
        },
    },
    subscriptions: {
        init({ dispatch, history }, done) {
            console.log('init');
        },
    },
};

export const appActions = actionBuilder(model);

export default model;
